package com.csthink.common.infrastructure.util;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

/**
 * @author <a href="mailto:security.2009@live.cn">Mars</a>
 * @since 2023-09-13
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public class JsonUtil {
    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static final ObjectMapper objectMapperIgnoreNull = new ObjectMapper();
    private static final ObjectMapper objectMapperIgnoreNullAndVisibleAll = new ObjectMapper();

    static {
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        objectMapperIgnoreNull.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        objectMapperIgnoreNullAndVisibleAll.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        objectMapperIgnoreNullAndVisibleAll.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    }

    public static <T> T objectToObject(Object obj, Class<T> clazz) {
        return objectMapper.convertValue(obj, clazz);
    }

    public static <T> T objectToObject(Object obj, TypeReference<T> toValueTypeRef) {
        return objectMapper.convertValue(obj, toValueTypeRef);
    }

    @SneakyThrows
    public static <T> T stringToObject(String str, Class<T> clazz) {
        return objectMapper.readValue(str, clazz);
    }

    @SneakyThrows
    public static <T> T stringToObject(String str, TypeReference<T> toValueTypeRef) {
        return objectMapper.readValue(str, toValueTypeRef);
    }

    @SneakyThrows
    public static String toJson(Object obj) {
        return objectMapperIgnoreNull.writeValueAsString(obj);
    }

    @SneakyThrows
    public static String toJSon(Object object) {
        return objectMapperIgnoreNullAndVisibleAll.writeValueAsString(object);
    }
}